module one {
	export class Monitor {
		public constructor() {
		}

		private onCalls: { [route: string]: { call: (data: any) => void, thisObj: any, count:number }[] } = {};
		
		once(route: string, callback: (data: any) => void, thisObj: any): boolean {
			return this.addCall(route, callback, thisObj, 1);
		}

		on(route: string, callback: (data: any) => void, thisObj: any): boolean {
			return this.addCall(route, callback, thisObj, -1);
		}

		private addCall(route: string, callback: (data: any) => void, thisObj: any, count:number):boolean {
			let tempCalls = this.onCalls[route];
			if (tempCalls == null) {
				tempCalls = this.onCalls[route] = [];
			}
			else {
				for (let i: number = 0; i < tempCalls.length; i++) {
					let t = tempCalls[i];
					if (t.call == callback && t.thisObj == thisObj) {
						console.error("已经存在回调" + route);
						return false;
					}
				}
			}

			tempCalls.push({ call: callback, thisObj: thisObj, count: count });

			return true;
		}

		off(route: string, callback: (data: any) => void, thisObj: any): boolean {
			let tempCalls = this.onCalls[route];
			if (tempCalls) {
				for (let i: number = 0; i < tempCalls.length; i++) {
					let t = tempCalls[i];
					if (t.call == callback && t.thisObj == thisObj) {
						tempCalls.splice(i, 1);
						return true;
					}
				}
			}

			return false;
		}

		emit(route: string, data: any): void {
			let tempCalls = this.onCalls[route];
			if (tempCalls == null) {
				return;
			}
			let length:number = tempCalls.length;
			let needCalls = tempCalls.concat();

			for (let i: number = 0; i < tempCalls.length; i++) {
				let t = tempCalls[i];
				if (t.call == null) {
					tempCalls.splice(i, 1);
					i--;
				}
				else {
					if (t.count == 1) {
						tempCalls.splice(i, 1);
						i--;
					}
				}
			}

			for (let i: number = 0; i < needCalls.length; i++) {
				let t = needCalls[i];
				if (t.call == null) {
					console.error("存在没有销毁的回调函数");
				}
				else {
					t.call.call(t.thisObj, data);
				}
			}
		}
	}

	export let monitor = new Monitor();
}